<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <script>
      // const a = 1;
      // function fn1() {
      //   function fn2() {
      //     console.log(a);
      //   }
      // }
      // fn1();

      // var b = 2;
      // function fn1() {
      //   debugger;
      //   var a = 1;
      //   function fn2() {
      //     console.log(a);
      //     console.log(b);
      //   }
      //   console.log(fn2);
      // }
      // fn1();

      var b = 2;
      function fn1() {
        var a = 1;
        var fn2 = function () {
          a++;
          console.log(a);
          console.log(b);
        };
        debugger;
        console.log(fn2);
        return fn2;
      }
      var fn2 = fn1();
      fn2 = null;

      /*
        1. 概念
          通过 chrome 开发者调试工具得知: 闭包本质是内部函数中的一个容器(非 js 对象), 这个容器中包含了引用的局部变量

        2. 产生原因
          ● 函数嵌套
          ● 内部函数引用外部函数的局部变量
          ● 调用外部函数时就会产生闭包

        3. 闭包的生命周期
          产生：当内部函数创建时
          死亡：当内部函数没有变量引用，成为垃圾对象，就会自动被GC(垃圾回收机制)自动回收

        4. 闭包作用：
          1. 延长局部变量生命周期（活的久点）
          2. 让函数外部可以间接操作函数内部的局部变量数据

        5. 闭包在项目中的应用
          1. React中复用函数的手段，高阶函数形式
          
          实际开发中很少使用闭包，我一般研究源码时发现闭包的场景，
          vue2响应式原理中数据劫持阶段，内部通过闭包形式保存dep对象，这个dep对象在vue2响应式原理非常重要
          源码：https://github.com/vuejs/vue/blob/main/src/core/observer/index.ts 128行开始  
    */
    </script>
  </body>
</html>
